package com.zt.bigdata.practise.javastrategy.chapter2;

import com.zt.bigdata.practise.javastrategy.chapter1.dto.Person;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.DoubleSupplier;
import java.util.function.IntConsumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
 * java.util.function包
 */
public class Chapter2 {
    public static void main(String[] args) {
        //2.1 Consumer接口
        List<String> strings = Arrays.asList("this", "is", "a", "list", "of", "strings");
        //接口传入一个泛型参数(generic argument)，不返回任何值;   void forEach(Consumer<? super T> action);
        strings.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.print(s + " ");
            }
        });
        System.out.println();
        strings.forEach(s -> System.out.print(s + " "));
        System.out.println();

        Arrays.asList(1, 2, 3, 4, 5, 6, 7)
                .stream()
                .mapToInt(x -> x.intValue())
                .forEach(new IntConsumer() {
                    @Override
                    public void accept(int value) {
                        System.out.print(value + " ");
                    }
                });

        Map<Integer, String> map = new HashMap() {{
            put(1, "a");
            put(2, "b");
        }};

        map.forEach(new BiConsumer<Integer, String>() {
            @Override
            public void accept(Integer integer, String s) {
                System.out.println(integer + " " + s);
            }
        });

        //2.2 Supplier接口 接口不传入参数，返回一 个值;

        DoubleSupplier doubleSupplier = new DoubleSupplier() {
            @Override
            public double getAsDouble() {
                return Math.random();
            }
        };
        System.out.println("Supplier 生产数据: " + doubleSupplier.getAsDouble());
        doubleSupplier = () -> Math.random();
        System.out.println("Supplier 生产数据: " + doubleSupplier.getAsDouble());
        doubleSupplier = Math::random;
        System.out.println("Supplier 生产数据: " + doubleSupplier.getAsDouble());

        List<String> names = Arrays.asList("Mal", "Wash", "Kaylee", "Inara",
                "Zoë", "Jayne", "Simon", "River", "Shepherd Book");
        Optional<String> first = names.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("C");
            }
        }).findFirst();

        System.out.println(first);
        //orElseGet 不存在 则用 Supplier接口生成一个值
        System.out.println(first.orElseGet(new Supplier<String>() {
            @Override
            public String get() {
                return "None";
            }
        }));

        System.out.println(
                first.orElse(
                        String.format("No result found in %s", names.stream().collect(Collectors.joining(", ")))
                ));

        //2.3 Predicate接口
        Iterable<Person> personNameStartWithS = getNamesByCondition(
                person -> person.getName().startsWith("S"),
                names.stream().map(name -> new Person(name)).collect(Collectors.toList()));

        //2.4 Function接口  T -> R  一对一
        //<R> Stream<R> map(Function<? super T, ? extends R> mapper);

    }

    public static <T> Iterable<T> getNamesByCondition(Predicate<T> condition, Iterable<T> list) {
        return StreamSupport.stream(list.spliterator(), true)
                .filter(condition)
                .collect(Collectors.toList());
    }

    public String getNamesOfLength(int length, String... names) {
        return Arrays.stream(names)
                .filter(s -> s.length() == length)
                .collect(Collectors.joining(", "));
    }

    public String getNamesStartingWith(String s, String... names) {
        return Arrays.stream(names)
                .filter(str -> str.startsWith(s))
                .collect(Collectors.joining(", "));
    }
}
